package gogo

import (
	"go2/log"
	"go2/pool"
	"gogo/http_v3"
	"io"
	"os"
	"runtime"
	"sync"
	"time"

	"net/http"
	"strings"
)

// 固定URL前缀的钩子结构体
type preMuxEntry struct {
	h       preHttpProcFunc
	pattern string
}

// 固定URL结构体
type staticMuxEntry struct {
	h       HttpProcFunc
	pattern string
}

// 含有":"的智能URL结构体
type imuxEntry struct {
	h         HttpProcFunc
	pattern   string
	urlParams []string
}

// URL转发结构体
type forwardMuxEntry struct {
	target  string
	pattern string
}

// 主机路由分组结构体
type hostMuxEntry struct {
	//静态路径匹配
	pm map[string]string

	//特殊STATE匹配
	sm map[int]staticMuxEntry

	//固定URL前缀特征匹配，钩子规则
	//map["GET"/"POST"][pattern]preMuxEntry
	pre_gm map[string]map[string]preMuxEntry

	//固定特征的URL匹配
	//map["GET"/"POST"][pattern]staticMuxEntry
	gm map[string]map[string]staticMuxEntry

	//含有":"的智能URL匹配
	//map["GET"/"POST"][]imuxEntry
	im map[string][]imuxEntry

	//URL转发匹配
	//map["GET"/"POST"][pattern]forwardMuxEntry
	fm map[string]map[string]forwardMuxEntry
}

func NewHttpRouterHandler() *HttpRouterHandler {
	return &HttpRouterHandler{
		hosts: make(map[string]*hostMuxEntry),
		forwardClient: &http.Client{
			Timeout: 30 * time.Second,
			Transport: &http.Transport{
				MaxIdleConns:        100,
				MaxIdleConnsPerHost: 10,
				IdleConnTimeout:     90 * time.Second,
				DisableCompression:  true, // 避免重复压缩
			},
		},
	}
}

// extractHostname 提取主机名，自动去掉端口号 - 优化版本
func (c *HttpRouterHandler) extractHostname(host string) string {
	if host == "" {
		return "*"
	}

	// 使用 strings.LastIndexByte 高效查找冒号位置
	if idx := strings.LastIndexByte(host, ':'); idx != -1 {
		host = host[:idx]
	}

	if host == "" {
		return "*"
	}

	return host
}

// getOrCreateHostEntry 获取或创建指定主机名的路由入口
func (c *HttpRouterHandler) getOrCreateHostEntry(host string) *hostMuxEntry {
	// 自动提取主机名，去掉端口号
	hostname := c.extractHostname(host)

	if entry, exists := c.hosts[hostname]; exists {
		return entry
	}

	entry := &hostMuxEntry{}
	c.hosts[hostname] = entry
	return entry
}

// hop-by-hop头部映射表 - 包级别常量,避免每次请求重复创建
var hopByHopHeaders = map[string]bool{
	"Connection":          true,
	"Proxy-Connection":    true,
	"Upgrade":             true,
	"Proxy-Authenticate":  true,
	"Proxy-Authorization": true,
	"Te":                  true,
	"Trailers":            true,
	"Transfer-Encoding":   true,
}

// URL参数map的sync.Pool - 减少GC压力
var urlParamsPool = sync.Pool{
	New: func() interface{} {
		return make(map[string]string)
	},
}

// HTTPContext的sync.Pool - 减少每次请求的内存分配
var httpContextPool = sync.Pool{
	New: func() interface{} {
		return &HTTPContext{}
	},
}

// 从Pool获取URL参数map
func getURLParamsMap() map[string]string {
	return urlParamsPool.Get().(map[string]string)
}

// 归还URL参数map到Pool
func putURLParamsMap(m map[string]string) {
	// 清空map
	for k := range m {
		delete(m, k)
	}
	urlParamsPool.Put(m)
}

// 从Pool获取HTTPContext
func getHTTPContext(w http.ResponseWriter, r *http.Request) *HTTPContext {
	ctx := httpContextPool.Get().(*HTTPContext)
	ctx.w = w
	ctx.r = r
	ctx.urlParams = nil
	ctx.body = nil
	return ctx
}

// 归还HTTPContext到Pool
func putHTTPContext(ctx *HTTPContext) {
	ctx.w = nil
	ctx.r = nil
	ctx.urlParams = nil
	ctx.body = nil
	httpContextPool.Put(ctx)
}

// HttpRouterHandler 保存注册函数的地方
type HttpRouterHandler struct {
	// 基于主机名的路由分组
	// map[hostname]hostMuxEntry
	hosts map[string]*hostMuxEntry

	// 全局HTTP客户端，支持连接复用
	forwardClient *http.Client
}

func GetProID(w http.ResponseWriter) int {
	if resp, ok := w.(*http_v3.Response); ok {
		return resp.ProID()
	}
	return runtime.NumGoroutine()
}

// ServeHTTP 官方HTTP触发入口 - 优化版本
func (c *HttpRouterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	log.Infof("pro %d: ServeHTTP: %s %s", GetProID(w), r.Host, r.URL.Path)

	// 获取主机名，自动去掉端口号
	hostname := c.extractHostname(r.Host)

	// 尝试获取指定主机的路由配置 - 优化查找逻辑
	entry, exists := c.hosts[hostname]
	if !exists {
		// 如果没有找到特定主机的配置，尝试使用默认主机配置
		entry, exists = c.hosts["*"]
		if !exists {
			// 如果没有任何配置，返回404
			http.NotFound(w, r)
			return
		}
	}

	// 使用Pool获取HTTPContext，减少内存分配
	pctx := getHTTPContext(w, r)
	defer putHTTPContext(pctx)

	method := r.Method
	urlPath := r.URL.Path

	// 执行前置钩子（如果存在）
	if methodPreHandlers, ok := entry.pre_gm[method]; ok {
		for prefix, proc := range methodPreHandlers {
			if strings.HasPrefix(urlPath, prefix) {
				if !proc.h.PreServeHTTP(pctx) {
					return
				}
			}
		}
	}

	// 优先匹配固定URL规则（最快，O(1)查找）
	if methodHandlers, ok := entry.gm[method]; ok {
		if handler, found := methodHandlers[urlPath]; found {
			handler.h.ServeHTTP(pctx)
			return
		}
	}

	// 匹配智能URL规则（带参数的路由）
	if methodImHandlers, ok := entry.im[method]; ok {
		for i := range methodImHandlers {
			v := &methodImHandlers[i]
			patternLen := len(v.pattern)

			// 优化：提前检查长度和前缀
			if len(urlPath) > patternLen && urlPath[patternLen] == '/' && urlPath[:patternLen] == v.pattern {
				remainingPath := urlPath[patternLen+1:]

				// 优化：快速计算参数数量，避免不必要的Split
				slashCount := strings.Count(remainingPath, "/")
				expectedParamCount := len(v.urlParams)

				if slashCount == expectedParamCount-1 {
					urlParams := strings.Split(remainingPath, "/")

					if len(urlParams) == expectedParamCount {
						extURLParams := getURLParamsMap()
						matched := true

						for idx, paramValue := range urlParams {
							paramName := v.urlParams[idx]
							if paramName[0] == ':' {
								extURLParams[paramName] = paramValue
							} else if paramValue != paramName {
								matched = false
								break
							}
						}

						if matched {
							pctx.urlParams = extURLParams
							v.h.ServeHTTP(pctx)
							putURLParamsMap(extURLParams)
							return
						}
						putURLParamsMap(extURLParams)
					}
				}
			}
		}
	}

	// 匹配URL转发规则
	if methodForwards, ok := entry.fm[method]; ok {
		for pattern, forward := range methodForwards {
			if strings.HasPrefix(urlPath, pattern) {
				c.serveHTTPForward(w, r, forward.target+urlPath[len(pattern):])
				return
			}
		}
	}

	// 匹配静态路径规则（仅GET请求）
	if method == "GET" && entry.pm != nil {
		for pattern, path := range entry.pm {
			if strings.HasPrefix(urlPath, pattern) {
				http.ServeFile(w, r, path+urlPath[len(pattern):])
				return
			}
		}
	}

	// 处理404
	if handler, ok := entry.sm[http.StatusNotFound]; ok {
		handler.h.ServeHTTP(pctx)
		return
	}

	// 如果当前主机配置中没有找到404处理器，但使用了默认主机配置
	// 尝试在原主机配置中查找404处理器
	if hostname != "*" {
		if hostEntry, exists := c.hosts[hostname]; exists {
			if handler, ok := hostEntry.sm[http.StatusNotFound]; ok {
				handler.h.ServeHTTP(pctx)
				return
			}
		}
	}

	// 默认404
	http.NotFound(w, r)
}

func (c *HttpRouterHandler) RegHTTPPublic(pattern, path string) {
	c.RegHTTPPublicWithHost("", pattern, path)
}

func (c *HttpRouterHandler) RegHTTPPublicWithHost(host, pattern, path string) {
	if pattern == "" {
		panic("http: invalid pattern")
	}
	if path == "" {
		panic("http: invalid path")
	}

	if strings.HasSuffix(pattern, "/") {
		pattern = pattern[:len(pattern)-1]
	}
	if strings.HasSuffix(path, "/") {
		path = path[:len(path)-1]
	}

	entry := c.getOrCreateHostEntry(host)

	if entry.pm == nil {
		entry.pm = make(map[string]string)
	} else {
		// 检查pattern是否之前已经添加过
		if _, exist := entry.pm[pattern]; exist {
			panic("http: multiple registrations for " + pattern)
		}
	}

	entry.pm[pattern] = path
}

func (c *HttpRouterHandler) RegHTTPPreFunc(method, pattern string, handler preHttpProcFunc) {
	c.RegHTTPPreFuncWithHost("", method, pattern, handler)
}

func (c *HttpRouterHandler) RegHTTPPreFuncWithHost(host, method, pattern string, handler preHttpProcFunc) {
	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	entry := c.getOrCreateHostEntry(host)

	//检查pattern是否之前已经添加过
	if entry.pre_gm != nil && entry.pre_gm[method] != nil {
		if _, exist := entry.pre_gm[method][pattern]; exist {
			panic("http: multiple registrations for " + pattern)
		}
	}

	if entry.pre_gm == nil {
		entry.pre_gm = make(map[string]map[string]preMuxEntry)
	}
	if entry.pre_gm[method] == nil {
		entry.pre_gm[method] = make(map[string]preMuxEntry)
	}

	entry.pre_gm[method][pattern] = preMuxEntry{h: handler, pattern: pattern}
}

// RegHTTPProcFunc 注册固定URL、解析URL函数
// method string: 请求方式，POST、GET、PUT、DELETE等
// pattern string：触发路径
// handler httpProcFunc: 触发函数
func (c *HttpRouterHandler) RegHTTPProcFunc(method, pattern string, handler HttpProcFunc) {
	c.RegHTTPProcFuncWithHost("", method, pattern, handler)
}

func (c *HttpRouterHandler) RegHTTPProcFuncWithHost(host, method, pattern string, handler HttpProcFunc) {
	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	entry := c.getOrCreateHostEntry(host)

	//检查pattern是否之前已经添加过
	if entry.gm != nil && entry.gm[method] != nil {
		if _, exist := entry.gm[method][pattern]; exist {
			panic("http: multiple registrations for " + pattern)
		}
	}
	if entry.im != nil && entry.im[method] != nil {
		// 这里需要检查智能路由中是否有相同的pattern，稍后实现
	}

	if entry.gm == nil {
		entry.gm = make(map[string]map[string]staticMuxEntry)
	}
	if entry.gm[method] == nil {
		entry.gm[method] = make(map[string]staticMuxEntry)
	}

	if entry.im == nil {
		entry.im = make(map[string][]imuxEntry)
	}
	if entry.im[method] == nil {
		entry.im[method] = []imuxEntry{}
	}

	istart := strings.Index(pattern, "/:")
	if istart == -1 {
		entry.gm[method][pattern] = staticMuxEntry{h: handler, pattern: pattern}
	} else {
		if istart <= 1 {
			log.Errorf("%s 错误,请不要以\\:开头!", pattern)
			os.Exit(0)
		} else {
			// 优化：避免不必要的字节切片转换
			ipattern := pattern[:istart]
			urlParams := strings.Split(pattern[istart+1:], "/")
			entry.im[method] = append(entry.im[method], imuxEntry{h: handler, urlParams: urlParams, pattern: ipattern})
		}
	}
}

// serveHTTPForward 处理URL转发 - 优化版本支持大数据流式传输
func (c *HttpRouterHandler) serveHTTPForward(w http.ResponseWriter, r *http.Request, targetURL string) {

	// 优化：使用 strings.Builder 构建完整URL
	var fullURL string
	if r.URL.RawQuery != "" {
		var urlBuilder strings.Builder
		urlBuilder.Grow(len(targetURL) + len(r.URL.RawQuery) + 1)
		urlBuilder.WriteString(targetURL)
		urlBuilder.WriteByte('?')
		urlBuilder.WriteString(r.URL.RawQuery)
		fullURL = urlBuilder.String()
	} else {
		fullURL = targetURL
	}

	// 创建目标请求
	req, err := http.NewRequest(r.Method, fullURL, r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		log.Errorf("pro %d, http.Client create: %v", GetProID(w), err)
		return
	}

	// 复制请求头，但排除hop-by-hop头 - 使用包级别常量
	for name, values := range r.Header {
		// 使用映射表快速判断
		if hopByHopHeaders[name] {
			continue
		}
		// 优化：直接赋值而不是逐个Add（性能更好）
		req.Header[name] = values
	}

	// 使用全局客户端发送请求（支持连接复用）
	resp, err := c.forwardClient.Do(req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		log.Errorf("pro %d, http.Client: %v", GetProID(w), err)
		return
	}
	defer resp.Body.Close()

	// 立即复制响应头并发送状态码，启用流式传输 - 优化版本
	for name, values := range resp.Header {
		// 使用映射表快速判断hop-by-hop头
		if hopByHopHeaders[name] {
			continue
		}
		// 优化：直接赋值而不是逐个Add
		w.Header()[name] = values
	}

	// 立即设置状态码，开始流式传输
	w.WriteHeader(resp.StatusCode)

	// 检查是否支持Flusher接口（用于流式传输）
	flusher, canFlush := w.(http.Flusher)

	// 使用更大的缓冲区提高大文件传输性能 - 优化版本
	const bufferSize = 256 * 1024 // 256KB缓冲区
	buf := pool.Malloc(bufferSize)
	defer pool.Free(buf)

	// 流式复制响应体 - 优化版本，减少系统调用
	var totalBytes int64
	for {
		n, err := resp.Body.Read(buf)
		if n > 0 {
			// 立即写入数据
			written, writeErr := w.Write(buf[:n])
			if writeErr != nil {
				log.Errorf("pro %d, Write Response: %v", GetProID(w), writeErr)
				return
			}
			totalBytes += int64(written)

			// 如果支持，立即刷新缓冲区
			if canFlush {
				flusher.Flush()
			}
		}
		if err != nil {
			if err == io.EOF {
				break // 正常结束
			}
			log.Errorf("pro %d, Read Response: %v", GetProID(w), err)
			return
		}
	}

	log.Debugf("pro %d, serveHTTPForward: %s, transferred: %d bytes", GetProID(w), fullURL, totalBytes)
}

func (c *HttpRouterHandler) RegHTTPStatusFunc(status int, handler HttpProcFunc) {
	c.RegHTTPStatusFuncWithHost("", status, handler)
}

func (c *HttpRouterHandler) RegHTTPStatusFuncWithHost(host string, status int, handler HttpProcFunc) {
	if status == 0 {
		panic("http: invalid status")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	entry := c.getOrCreateHostEntry(host)

	if entry.sm == nil {
		entry.sm = make(map[int]staticMuxEntry)
	}

	entry.sm[status] = staticMuxEntry{h: handler, pattern: "404"}
}

// RegHTTPForward 注册指定HTTP方法的URL转发规则
// method string: 请求方式，POST、GET、PUT、DELETE等
// pattern string：触发路径
// target string: 目标URL
func (c *HttpRouterHandler) RegHTTPForward(method, pattern, target string) {
	c.RegHTTPForwardWithHost("", method, pattern, target)
}

func (c *HttpRouterHandler) RegHTTPForwardWithHost(host, method, pattern, target string) {
	if method == "" {
		panic("http: invalid method")
	}
	if pattern == "" {
		panic("http: invalid pattern")
	}
	if target == "" {
		panic("http: invalid target")
	}

	if strings.HasSuffix(pattern, "/") {
		pattern = pattern[:len(pattern)-1]
	}
	if strings.HasSuffix(target, "/") {
		target = target[:len(target)-1]
	}

	method = strings.ToUpper(method)

	entry := c.getOrCreateHostEntry(host)

	if entry.fm == nil {
		entry.fm = make(map[string]map[string]forwardMuxEntry)
	}
	if entry.fm[method] == nil {
		entry.fm[method] = make(map[string]forwardMuxEntry)
	}

	//检查pattern是否之前已经添加过
	if _, exist := entry.fm[method][pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	entry.fm[method][pattern] = forwardMuxEntry{target: target, pattern: pattern}
}
